package com.lipaluma.context.mapping.impl;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import com.lipaluma.context.mapping.BasicMappingManager;
import com.lipaluma.field.mapper.mapping.MappingInfo;
import com.lipaluma.field.mapper.mapping.MappingOptions;
import com.lipaluma.util.ReflectionUtils;

//TODO : faire en sorte d'utiliser la méthode getTargetClass pour connaitre la class réel à mapper.
// ce sera à utiliser par l'ObjectFieldMapper.
// 
public class BuilderMappingManager implements BasicMappingManager {
	private Map<Field, List<MappingInfo>> mapMappings = new HashMap<Field, List<MappingInfo>>();
	private Map<Field, MappingOptions.Builder> mapOptions = new HashMap<Field, MappingOptions.Builder>();
	private List<Field> oneToManyFields = new ArrayList<Field>();
	
	public void addMappings(Field field, MappingInfo... mappings) {
		if(mappings == null || mappings.length == 0)
			return;		
		List<MappingInfo> list = mapMappings.get(field);
		if(list == null)
			mapMappings.put(field, new ArrayList<MappingInfo>());
		List<MappingInfo> mappingsAsList = Arrays.asList(mappings);
		mapMappings.get(field).addAll(mappingsAsList);
	}

	@Override
	public MappingInfo initMapping(Field field) {
		if(mapMappings.get(field) == null)
			return null;
		return mapMappings.get(field).get(0);
	}

	public void addPattern(Field field, String pattern) {
		if(mapOptions.get(field) == null)
			mapOptions.put(field, MappingOptions.builder());
		mapOptions.get(field).withPattern(pattern);
	}
	public void addSeparator(Field field, String separator) {
		if(mapOptions.get(field) == null)
			mapOptions.put(field, MappingOptions.builder());
		mapOptions.get(field).withSeparator(separator);
	}
	public void addLocale(Field field, Locale locale) {
		if(mapOptions.get(field) == null)
			mapOptions.put(field, MappingOptions.builder());
		mapOptions.get(field).withLocale(locale);
	}
	public void addFalseValues(Field field, String... falseValues) {
		if(mapOptions.get(field) == null)
			mapOptions.put(field, MappingOptions.builder());
		mapOptions.get(field).withFalseValues(falseValues);
	}
	public void addTrueValues(Field field, String... trueValues) {
		if(mapOptions.get(field) == null)
			mapOptions.put(field, MappingOptions.builder());
		mapOptions.get(field).withTrueValues(trueValues);
	}
	public void isKeepAll(Field field, boolean keepAll) {
		if(mapOptions.get(field) == null)
			mapOptions.put(field, MappingOptions.builder());
		mapOptions.get(field).isAllkeeped(keepAll);
	}
	
	@Override
	public List<? extends MappingInfo> initMultipleMappings(Field field) {
		return mapMappings.get(field);
	}

	@Override
	public MappingOptions initOptions(Field field) {
		if(mapOptions.get(field) == null)
			return null;
		return mapOptions.get(field).build();
	}

	public void defineAsOneToMany(Field field) {
		oneToManyFields.add(field);
	}
	
	@Override
	public Class<?> getTargetClass(Field field) {
		Class<?> targetClass;
		if(isOneToMany(field))
			targetClass = ReflectionUtils.getParameterizedClass(field);
		else
			targetClass = field.getType();
		return targetClass;
	}

	public boolean isOneToMany(Field field) {
		return oneToManyFields.contains(field);
	}

}
